#include "ByteStream.h"

using namespace OOPUtils;
using namespace std;

ByteStream::ByteStream () : _data (NULL), _length (0),
  _wpos (0), _capacity (0), _rpos (0) {}



ByteStream::ByteStream (const char * data, size_t length)
  : _wpos (length), _rpos (0), _capacity (length),
  _data (new char[length]), _length (length)
{
  memcpy (_data, data, length);
}



ByteStream::ByteStream (const ByteStream & right)
  : _length (right._length), _wpos (right._wpos), _rpos (right._rpos),
  _capacity (right._capacity), _data (new char [_capacity])
{
  memcpy (_data, right._data, _length);
}



ByteStream::~ByteStream ()
{
  if (_data)
    delete [] _data;
}



const char * ByteStream::getBytes () const
{
  return _data;
}

size_t ByteStream::getLength () const
{
  return _length;
}

ByteStream & ByteStream::operator<< (const char & right)
{
  throw ("Not implemented!");
  return *this;
}

ByteStream & ByteStream::operator<< (const int & right)
{
  throw ("Not implemented!");
  return *this;
}

ByteStream & ByteStream::operator<< (const float & right)
{
  throw ("Not implemented!");
  return *this;
}

ByteStream & ByteStream::operator<< (const double & right)
{
  throw ("Not implemented!");
  return *this;
}

ByteStream & ByteStream::operator<< (const bool & right)
{
  throw ("Not implemented!");
  return *this;
}

ByteStream & ByteStream::operator<< (const char * right)
{
  size_t strLength = strlen (right);
  _expandTo (_wpos + strLength);
  memcpy (_data + _length, right, strLength);
  return *this;
}

ByteStream & ByteStream::operator<< (const string & right)
{
  size_t strLength = right.size () + 1;
  _expandTo (_wpos + strLength);
  memcpy (_data + _length, right.c_str (), strLength);
  return *this;
}

const ByteStream & ByteStream::operator>> (char & right) const
{
  throw ("Not implemented!");
  return *this;
}

const ByteStream & ByteStream::operator>> (int & right) const
{
  throw ("Not implemented!");
  return *this;
}

const ByteStream & ByteStream::operator>> (float & right) const
{
  throw ("Not implemented!");
  return *this;
}

const ByteStream & ByteStream::operator>> (double & right) const
{
  throw ("Not implemented!");
  return *this;
}

const ByteStream & ByteStream::operator>> (bool & right) const
{
  throw ("Not implemented!");
  return *this;
}

void ByteStream::_expandTo (size_t newSize)
{
  if (newSize > _capacity) // Space not enough
  {
    // Allocate a new space
    if (_data != NULL)
    {
      _capacity *= 2;
      char * newSpace = new char[_capacity];
      memcpy (newSpace, _data, _length);
      delete [] _data;
      _data = newSpace;
    }
    else
    {
      _capacity = newSize;
      _data = new char[_capacity];
    }
  }

  if (_length < newSize)
    _length = newSize;
  _wpos = newSize;

}